using System;
using System.IO;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Globalization;
using System.Xml;

namespace CopyTimer
{
    public class Utility
    {
        protected enum ResourceState
        {
            // Fields
            File = 0,
            Folder = 1,
            NotFound = 2
        }

        const int BUFFER_SIZE = 1024;

        private CredentialCache credentialCache = new CredentialCache();

        private int requestTimeout = 900000;    //this is for the entire operation.... complete send 900k timeout = 15 minutes
        private int readWriteTimeout = 30000;  //this is for communication back and forth, each one needs to be within a certain time

		private static string strUserAgent = "CopyTimer Utility"; //null

        public Utility()
        {
            ServicePointManager.CertificatePolicy = new TrustEveryoneCertificatePolicy(); 
        }

        public UtilityOperationResults CopyFile(string source, string destination, bool bOverWrite)
        {
            UtilityOperationResults OpsResults = new UtilityOperationResults();
            Stream sourceStream = null;
            Stream destinationStream = null;
            HttpWebRequest sourceRequest = null;
            HttpWebRequest destinationRequest = null;
            HttpWebResponse sourceResponse = null;
            HttpWebResponse destinationResponse = null;

            long sourceLength = 0;
            ResourceState SourceState;
            ResourceState DestinationState;

            Uri sourceUri = GetURI(source);
            Uri destinationUri = GetURI(destination);

            OpsResults.OperationStartTime = DateTime.Now;   //get the time (which may be a different culture)

            try
            {
                //setup source stream
                if (sourceUri != null)
                {
                    SourceState = GetResourceState(sourceUri);
                }
                else
                {
                    SourceState = GetResourceState(source);
                }
                
                if (SourceState == ResourceState.Folder)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Source cannot be a folder";
                    return OpsResults;
                }
                if (SourceState == ResourceState.NotFound)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Source cannot be found";
                    return OpsResults;
                }
                
                if (sourceUri != null)
                {
                    sourceRequest = (HttpWebRequest)WebRequest.CreateDefault(sourceUri);
                    sourceRequest.Credentials = credentialCache;
                    sourceRequest.Method = "GET";
                    sourceRequest.Timeout = requestTimeout;
					sourceRequest.ReadWriteTimeout = readWriteTimeout;
                    sourceRequest.UserAgent = strUserAgent;
                    sourceRequest.Headers.Add("Translate", "F");
                    sourceResponse = (HttpWebResponse)sourceRequest.GetResponse();
                    sourceStream = sourceResponse.GetResponseStream();
                    sourceLength = sourceResponse.ContentLength;
                   
                }
                else
                {
                    sourceStream = new FileStream(source, FileMode.Open, FileAccess.Read);
                    sourceLength = sourceStream.Length;
                }
                

                //setup destination stream
                if (destinationUri != null)
                {
                    DestinationState = GetResourceState(destinationUri);
                }
                else
                {
                    DestinationState = GetResourceState(destination);
                }
                
                if (DestinationState == ResourceState.Folder)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Destination cannot be a folder";
                    return OpsResults;
                }
                if (!bOverWrite && (DestinationState == ResourceState.File))
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Destination file already exists";
                    return OpsResults;
                }
                
                if (destinationUri != null)
                {
					destinationRequest = (HttpWebRequest)WebRequest.CreateDefault(destinationUri);
					destinationRequest.ContentLength = sourceStream.Length;
					destinationRequest.Credentials = this.credentialCache;
					destinationRequest.Method = "PUT";
					destinationRequest.Timeout = this.requestTimeout;
					destinationRequest.ReadWriteTimeout = this.readWriteTimeout;
					destinationRequest.UserAgent = strUserAgent;
					destinationRequest.Headers.Add("Translate", "F");
					destinationStream = destinationRequest.GetRequestStream();
				}
                else
                {
                    destinationStream = new FileStream(destination, FileMode.OpenOrCreate, FileAccess.Write);
                }
//                //copy file contents
//                for (long sourceStreamPosition = 0; sourceStreamPosition < sourceLength; sourceStreamPosition++)
//                {
//                    destinationStream.WriteByte((byte)sourceStream.ReadByte());
//                    OpsResults.TransferSize++;
//                }

                int copymethod = 1;

                if (copymethod == 1) //sean k's transfer method
                {
                    byte[] contents = new byte[sourceLength];
                    //int loopCount = 0;

                    while (true)
                    {
                        //int bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
                        int bytesRead = sourceStream.Read(contents, 0, (int)sourceLength);
                        //Console.WriteLine("Bytes Read: {0}", bytesRead);
                        if (bytesRead == 0)
                            break;
                        destinationStream.Write(contents, 0, bytesRead);
                        OpsResults.TransferSize += bytesRead;
                        //loopCount++;
                    }
                    //Console.WriteLine("Number of loops: {0}", loopCount);
                }
                else   // sean l's transfer method
                {                  
                   //A Higher speed copy routine is below, this should work at a more constant speed across different platforms
                   byte[] buffer = new byte[8192];
                   while (true)
                   {
                       int bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
                       if (bytesRead == 0)
                           break;
                       destinationStream.Write(buffer, 0, bytesRead);
                       OpsResults.TransferSize += bytesRead;
                   }
                 
                }
                if (destinationUri != null)
                {
                    destinationResponse = ((HttpWebResponse)destinationRequest.GetResponse());

////Async Calling Code
//					RequestState destRequestState = new RequestState();  
//					destRequestState.request = destinationRequest;
//					// Start the asynchronous request.
//					IAsyncResult result = (IAsyncResult) destinationRequest.BeginGetResponse(new AsyncCallback(RespCallback),destRequestState);
//					// this line impliments the timeout, if there is a timeout, the callback fires and the request becomes aborted
//					ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), destinationRequest, DefaultTimeout, true);
//					// The response came in the allowed time. The work processing will happen in the callback function.
//					allDone.WaitOne();
//					allDone.Reset();
//					// Release the HttpWebResponse resource.
//					//destRequestState.response.Close();
//					destinationResponse = (HttpWebResponse)destRequestState.response;

					if (destinationResponse.StatusCode == HttpStatusCode.Created)
                    {
                        OpsResults.OperationEndTime = DateTime.Now;
                        OpsResults.Message = "File copied successfully";
                        OpsResults.Success = true;
                    }
                    else
                    {
                        OpsResults.OperationEndTime = DateTime.Now;
                        OpsResults.Message = "Error: " + destinationResponse.StatusDescription;
                        OpsResults.Success = false;
                    }
                }
                else
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "File copied successfully";
                    OpsResults.Success = true;
                }
                return OpsResults;
            }
            catch (IOException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "IO Exception";
                OpsResults.Success = false;
                return OpsResults;
            }
            catch (UnauthorizedAccessException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "Unauthorized access";
                OpsResults.Success = false;
                return OpsResults;
            }
            catch (WebException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                
                WebExceptionStatus ExceptionStatus = e.Status;
                if (ExceptionStatus != WebExceptionStatus.ConnectFailure)
                {
                    if (ExceptionStatus == WebExceptionStatus.ProtocolError)
                    {
                        HttpWebResponse ErrorResponse = (HttpWebResponse)e.Response;
                        try
                        {
                            if (ErrorResponse.StatusCode == HttpStatusCode.RequestUriTooLong)
                            {
                                OpsResults.Message = "Request Uri too long";
                            }
                            else if ((ErrorResponse.StatusCode == HttpStatusCode.Conflict))  //after the upload finished the server said 409 which could mean an app pool recycle or alot of other things
                            {
                                if (sourceLength == (long)OpsResults.TransferSize)    //make sure they transfered all the bytes
                                {
                                    OpsResults.Message = "Success but HTTP Status Code: " + ErrorResponse.StatusCode;    //regardless the time is still valid and can be used
                                    OpsResults.Success = true;
                                }
                                else
                                {
                                    OpsResults.Message = "Failed. Upload did not finish with HTTP Status Code: " + ErrorResponse.StatusCode;    //regardless the time is still valid and can be used
                                    OpsResults.Success = false; 
                                }
                            }
                            else
                            {
                                OpsResults.Message = "ERROR: Status Code: " + ErrorResponse.StatusCode + " " + ErrorResponse.StatusDescription;
                            }
                        }
                        finally
                        {
                            if (ErrorResponse != null)
                            {
                                ((IDisposable)ErrorResponse).Dispose();
                            }
                        }
                    }
                    else
                    {
                        if (ExceptionStatus != WebExceptionStatus.Timeout)
                        { 
                            OpsResults.Message = "Web exception: " + ExceptionStatus.ToString();
                        }
                        else
                        {
                            OpsResults.Message = "Timeout";
                        }
                    }
                }
                else
                {
                    OpsResults.Message = "ConnectFailure";
                }
                return OpsResults;
            }
            catch (Exception e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "Unknown exception: " + e.ToString();
                OpsResults.Success = false;
                return OpsResults;
            }
            finally
            {
                if (destinationStream != null)
                {
                    destinationStream.Close();
                }
                if (sourceStream != null)
                {
                    sourceStream.Close();
                }

                if (sourceResponse != null)
                {
                    sourceResponse.Close();
                }
                if (destinationResponse != null)
                {
                    destinationResponse.Close();
                }
            }
        }

        public UtilityOperationResults CreateFolder(string target)
        {
            UtilityOperationResults OpsResults = new UtilityOperationResults();
            ResourceState targetState;
            Uri targetUri = GetURI(target);

            //make the folderURI if it is possible
            OpsResults.OperationStartTime = DateTime.Now;
            try
            {
                if (targetUri != null)
                {
                    targetState = GetResourceState(targetUri);
                }
                else
                {
                    targetState = GetResourceState(target);
                }

                if (targetState == ResourceState.File)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Target cannot be a file";
                    return OpsResults;
                }
                if (targetState != ResourceState.NotFound)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Target already exists";
                    return OpsResults;
                }
                if (targetUri != null)
                {
                    HttpWebRequest targetRequest = (HttpWebRequest)WebRequest.CreateDefault(targetUri);
                    targetRequest.Credentials = credentialCache;
                    targetRequest.Method = "MKCOL";
                    targetRequest.Timeout = requestTimeout;
                    targetRequest.UserAgent = strUserAgent;
                    HttpWebResponse targetResponse = ((HttpWebResponse)targetRequest.GetResponse());
                    if (targetResponse.StatusCode == HttpStatusCode.Created)
                    {
                        OpsResults.OperationEndTime = DateTime.Now;
                        OpsResults.Message = "Folder created successfully";
                        OpsResults.Success = true;
                    }
                    else
                    {
                        OpsResults.OperationEndTime = DateTime.Now;
                        OpsResults.Message = "Error: " + targetResponse.StatusDescription;
                        OpsResults.Success = false;
                    }
                }
                else
                {
                    Directory.CreateDirectory(target);
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Folder created successfully";
                    OpsResults.Success = true;
                }
                return OpsResults;
            }
            catch (IOException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "IO Exception";
                return OpsResults;
            }
            catch (UnauthorizedAccessException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "Unauthorized access";
                return OpsResults;
            }
            catch (WebException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;

                WebExceptionStatus ExceptionStatus = e.Status;
                if (ExceptionStatus != WebExceptionStatus.ConnectFailure)
                {
                    if (ExceptionStatus == WebExceptionStatus.ProtocolError)
                    {
                        HttpWebResponse ErrorResponse = (HttpWebResponse)e.Response;
                        try
                        {
                            OpsResults.Message = "Unexpected HTTP error: " + ErrorResponse.StatusDescription;
                        }
                        finally
                        {
                            if (ErrorResponse != null)
                            {
                                ((IDisposable)ErrorResponse).Dispose();
                            }
                        }
                    }
                    else
                    {
                        if (ExceptionStatus != WebExceptionStatus.Timeout)
                        {
                            OpsResults.Message = "Unknown web exception";
                        }
                        else
                        {
                            OpsResults.Message = "Timeout";
                        }
                    }
                }
                else
                {
                    OpsResults.Message = "ConnectFailure";
                }
                return OpsResults;
            }
            catch (Exception e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "Unknown exception";
                return OpsResults;
            }
        }

        public UtilityOperationResults DeleteFile(string target)
        {
            UtilityOperationResults OpsResults = new UtilityOperationResults(); 
            ResourceState targetState;
            Uri targetUri = GetURI(target);

            OpsResults.OperationStartTime = DateTime.Now;
            try
            {
                if (targetUri != null)
                {
                    targetState = GetResourceState(targetUri);
                }
                else
                {
                    targetState = GetResourceState(target);
                }

                if (targetState == ResourceState.Folder)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Target cannot be a folder";
                    return OpsResults;
                }
                if (targetState == ResourceState.NotFound)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Target cannot be found";
                    return OpsResults;
                }
                if (targetUri != null)
                {
                    HttpWebRequest targetRequest = (HttpWebRequest)WebRequest.CreateDefault(targetUri);
                    targetRequest.Credentials = this.credentialCache;
                    targetRequest.Method = "DELETE";
                    targetRequest.Timeout = this.requestTimeout;
                    targetRequest.UserAgent = strUserAgent;
                    targetRequest.Headers.Add("Translate", "F");
                    HttpWebResponse targetResponse = ((HttpWebResponse)targetRequest.GetResponse());

                    //NoConent = Equivalent to HTTP status 204. HttpStatusCode.NoContent indicates that the request has been successfully processed and that the response is intentionally blank.
                    if ( (targetResponse.StatusCode == HttpStatusCode.OK) || (targetResponse.StatusCode == HttpStatusCode.NoContent) )
                    {
                        OpsResults.OperationEndTime = DateTime.Now;
                        OpsResults.Message = "File deleted successfully";
                        OpsResults.Success = true;
                    }
                    else
                    {
                        OpsResults.OperationEndTime = DateTime.Now;
                        OpsResults.Message = "Error: " + targetResponse.StatusDescription;
                        OpsResults.Success = false;
                    }
                }
                else
                {
                    File.Delete(target);
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "File deleted successfully";
                    OpsResults.Success = true;
                }
                return OpsResults;
            }
            catch (IOException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "IO Exception";
                return OpsResults;
            }
            catch (UnauthorizedAccessException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "Unauthorized access";
                return OpsResults;
            }
            catch (WebException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;

                WebExceptionStatus ExceptionStatus = e.Status;
                if (ExceptionStatus != WebExceptionStatus.ConnectFailure)
                {
                    if (ExceptionStatus == WebExceptionStatus.ProtocolError)
                    {
                        HttpWebResponse ErrorResponse = (HttpWebResponse)e.Response;
                        try
                        {
							OpsResults.Message = "Unexpected HTTP error: " + ErrorResponse.StatusDescription;
                        }
                        finally
                        {
                            if (ErrorResponse != null)
                            {
                                ((IDisposable)ErrorResponse).Dispose();
                            }
                        }
                    }
                    else
                    {
                        if (ExceptionStatus != WebExceptionStatus.Timeout)
                        {
                            OpsResults.Message = "Unknown web exception";
                        }
                        else
                        {
                            OpsResults.Message = "Timeout";
                        }
                    }
                }
                else
                {
                    OpsResults.Message = "ConnectFailure";
                }
                return OpsResults;
            }
            catch (Exception e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "Unknown exception";
                return OpsResults;
            }
        }

        public UtilityOperationResults DeleteFolder(string target)
        {
            UtilityOperationResults OpsResults = new UtilityOperationResults();
            ResourceState targetState;
            Uri targetUri = GetURI(target);

            OpsResults.OperationStartTime = DateTime.Now;
            try
            {
                if (targetUri != null)
                {
                    targetState = GetResourceState(targetUri);
                }
                else
                {
                    targetState = GetResourceState(target);
                }
                
                if (targetState == ResourceState.File)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Target cannot be a file";
                    return OpsResults;
                }
                if (targetState == ResourceState.NotFound)
                {
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Target cannot be found";
                    return OpsResults;
                }
                if (targetUri != null)
                {
                    HttpWebRequest targetRequest = (HttpWebRequest)WebRequest.CreateDefault(targetUri);
                    targetRequest.Credentials = this.credentialCache;
                    targetRequest.Method = "DELETE";
                    targetRequest.Timeout = this.requestTimeout;
                    targetRequest.UserAgent = strUserAgent;
                    targetRequest.Headers.Add("Translate", "F");
                    HttpWebResponse targetResponse = ((HttpWebResponse)targetRequest.GetResponse());
                    if ( (targetResponse.StatusCode == HttpStatusCode.OK) || (targetResponse.StatusCode == HttpStatusCode.NoContent) )
                    {
                        OpsResults.OperationEndTime = DateTime.Now;
                        OpsResults.Message = "Folder deleted successfully";
                        OpsResults.Success = true;
                    }
                    else
                    {
                        OpsResults.OperationEndTime = DateTime.Now;
                        OpsResults.Message = "Error: " + targetResponse.StatusDescription;
                        OpsResults.Success = false;
                    }
                }
                else
                {
                    Directory.Delete(target);
                    OpsResults.OperationEndTime = DateTime.Now;
                    OpsResults.Message = "Folder deleted successfully";
                    OpsResults.Success = true;
                }
                return OpsResults;
            }
            catch (IOException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "IO Exception";
                return OpsResults;
            }
            catch (UnauthorizedAccessException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "Unauthorized access";
                return OpsResults;
            }
            catch (WebException e)
            {
                OpsResults.OperationEndTime = DateTime.Now;

                WebExceptionStatus ExceptionStatus = e.Status;
                if (ExceptionStatus != WebExceptionStatus.ConnectFailure)
                {
                    if (ExceptionStatus == WebExceptionStatus.ProtocolError)
                    {
                        HttpWebResponse ErrorResponse = (HttpWebResponse)e.Response;
                        try
                        {
                            OpsResults.Message = "Unexpected HTTP error: " + ErrorResponse.StatusDescription;
                        }
                        finally
                        {
                            if (ErrorResponse != null)
                            {
                                ((IDisposable)ErrorResponse).Dispose();
                            }
                        }
                    }
                    else
                    {
                        if (ExceptionStatus != WebExceptionStatus.Timeout)
                        {
                            OpsResults.Message = "Unknown web exception";
                        }
                        else
                        {
                            OpsResults.Message = "Timeout";
                        }
                    }
                }
                else
                {
                    OpsResults.Message = "ConnectFailure";
                }
                return OpsResults;
            }
            catch (Exception e)
            {
                OpsResults.OperationEndTime = DateTime.Now;
                OpsResults.Message = "Unknown exception";
                return OpsResults;
            }
        }

        private Uri GetURI(string location)
        {
            Uri locationUri = null;
            try
            {
                locationUri = new Uri(location);
                if (credentialCache.GetCredential(locationUri, "NTLM") == null)
                {
                    credentialCache.Add(new Uri(locationUri.GetLeftPart(UriPartial.Authority)), "NTLM", (NetworkCredential)CredentialCache.DefaultCredentials);
                }
            }
            catch
            {
                locationUri = null;
            }
            return locationUri;
        }

        private ResourceState GetResourceState(Uri resourceUri)
        {
            try
            {
                using (HttpWebResponse ResResponse = GetResourceProperties(resourceUri))
                {
                    using (StreamReader srResponseStream = new StreamReader(ResResponse.GetResponseStream()))
                    {
                        XmlDocument xdResponse = new XmlDocument();
                        xdResponse.LoadXml(srResponseStream.ReadToEnd());
                        XmlNamespaceManager nsManager = new XmlNamespaceManager(xdResponse.NameTable);
                        nsManager.AddNamespace("D", "DAV:");
                        XmlNodeList xnlNodes = xdResponse.SelectNodes("/D:multistatus/D:response[D:propstat/D:prop/D:iscollection]", nsManager);
                        if (xnlNodes.Count == 1)
                        {
                            return ResourceState.Folder;
                        }
                        return ResourceState.File;
                    }
                }
            }
            catch (WebException e)
            {
                if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    using (HttpWebResponse ErrorResponse = ((HttpWebResponse)e.Response))
                    {
                        if (ErrorResponse.StatusCode == HttpStatusCode.NotFound)
                        {
                            return ResourceState.NotFound;
                        }
                    }
                }
                throw;
            }
        }

        private ResourceState GetResourceState(string resource)
        {
            try
            {
                if (Directory.Exists(resource))
                {
                    return ResourceState.Folder;
                }
                else if (File.Exists(resource))
                {
                    return ResourceState.File;
                }
                else
                {
                    return ResourceState.NotFound;
                }
            }
            catch (IOException e)
            {
                return ResourceState.NotFound;
            }
            catch (UnauthorizedAccessException e)
            {
                return ResourceState.NotFound;
            }
            catch (Exception e)
            {
                throw;
                //				return ResourceState.NotFound;
            }
        }

        /// <summary>
        /// Get the Resource Properties from a webdav request
        /// </summary>
        /// <param name="resourceUri">URI of the resource to check</param>
        /// <returns>An HTTPWebResponse object that contains the return value of the request</returns>
        protected HttpWebResponse GetResourceProperties(Uri resourceUri)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.CreateDefault(resourceUri);
            request.Credentials = credentialCache;
            request.Method = "PROPFIND";
            request.Timeout = requestTimeout;
            request.UserAgent = strUserAgent;
            request.Headers.Add("Depth", "0");
            request.Headers.Add("Translate", "F");
            return (HttpWebResponse)request.GetResponse();
        }
	}

    public class UtilityOperationResults
    {
        bool bSuccess;
        string strMessage;
        DateTime dtOperationStartTime;
        DateTime dtOperationEndTime;
        public int TransferSize;

        public UtilityOperationResults()
        {
            this.bSuccess = false;
            this.strMessage = "";
            this.dtOperationStartTime = new DateTime();
            this.dtOperationEndTime = new DateTime();
            this.TransferSize = 0;
        }

        public UtilityOperationResults(bool Success, string Message, DateTime OperationStartTime, DateTime OperationEndTime, int TransferSize)
        {
            this.bSuccess = false;
            this.strMessage = Message;
            this.dtOperationStartTime = OperationStartTime;
            this.dtOperationEndTime = OperationEndTime;
            this.TransferSize = TransferSize;
        }

        public bool Success
        {
            get { return this.bSuccess; }
            set { this.bSuccess = value; }
        }

        public string Message
        {
            get { return this.strMessage; }
            set { this.strMessage = value; }
        }

        public TimeSpan OperationTime
        {
            get { return (TimeSpan)(this.dtOperationEndTime - this.dtOperationStartTime); }
        }

        public DateTime OperationStartTime
        {
            get { return this.dtOperationStartTime; }
            set { this.dtOperationStartTime = value; }
        }

        public DateTime OperationEndTime
        {
            get { return this.dtOperationEndTime; }
            set { this.dtOperationEndTime = value; }
        }

//        public int TransferSize
//        {
//            get { return this.iTransferSize; }
//            set { this.iTransferSize = value; }
//        }

        public override string ToString()
        {
            IFormatProvider culture = new CultureInfo("en-US", false);  //convert the datetimes to US for printout

            string return_results = String.Format("<Results Success='{0}' Start='{1}' End='{2}' ", this.bSuccess, this.dtOperationStartTime.ToString(), this.dtOperationEndTime.ToString()) +
                String.Format("OperationTime='{0}' TransferSize='{1}'>{2}</Results>", ((TimeSpan)(this.dtOperationEndTime - this.dtOperationStartTime)).TotalSeconds.ToString(culture), this.TransferSize, this.strMessage);

            return return_results;
        }
    }

	public class RequestState
	{
		// This class stores the State of the request.
		const int BUFFER_SIZE = 1024;
		public StringBuilder requestData;
		public byte[] BufferRead;
		public HttpWebRequest request;
		public HttpWebResponse response;
		public Stream streamResponse;
		public RequestState()
		{
			BufferRead = new byte[BUFFER_SIZE];
			requestData = new StringBuilder("");
			request = null;
			streamResponse = null;
		}
	}

    public class TrustEveryoneCertificatePolicy : ICertificatePolicy
    {
        // Methods
        public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certificate, WebRequest request, int certificateProblem)
        {
            return true;
        }
    }
}
